package gnssio

import (
	"bufio"
	"dgo/goutils/utils"
	"os"
	"strings"
	"time"
)

type CommRawFileWriter struct {
	file        *os.File
	fileWriter  *bufio.Writer
	lastfile    string
	IsUtcTime   bool
	WBufSize    int
	GetTimeCB   func() time.Time
	FileNameFmt string //"$yyyy$/$mm$/G06$dd$.E"
}

func NewRawFileWriter(filefmt string) *CommRawFileWriter {
	return &CommRawFileWriter{
		IsUtcTime:   false,
		FileNameFmt: filefmt,
	}
}

// =================================================================
func (this *CommRawFileWriter) Start() {
	_t := time.Now()
	if this.IsUtcTime {
		_t = _t.UTC()
	}
	if this.IsUtcTime {
		utils.Log.Debugf("输出文件(当前)(采用UTC时间):%s", this.currFile(_t))
	} else {
		utils.Log.Debugf("输出文件(当前)(采用本地时间):%s", this.currFile(_t))
	}

}

func (this *CommRawFileWriter) Stop() {
	if this.file != nil {
		this.fileWriter.Flush()
		this.fileWriter = nil
		this.file.Close()
		this.file = nil
	}

}

func (this *CommRawFileWriter) Send(buf []byte, len int) int {
	r := this.checkNewFile()
	if r == -1 {
		return r
	}
	if this.tryWriteFile(buf[:len]) {
		return len
	} else {
		return -1
	}

}

func (this *CommRawFileWriter) AddListener(event I_CommListener) {
}

func (this *CommRawFileWriter) RemoveListener(event I_CommListener) {
}

func (this *CommRawFileWriter) currFile(_t time.Time) string {
	str := this.FileNameFmt
	str = utils.ParseTimeFmt(str, _t)
	return str
}

func (this *CommRawFileWriter) checkNewFile() int {
	_t := time.Now()
	if this.GetTimeCB != nil {
		_t = this.GetTimeCB()
	}
	if this.IsUtcTime {
		_t = _t.UTC()
	}

	str := this.currFile(_t)

	if strings.Compare(this.lastfile, str) != 0 {
		err := utils.CheckRotateFile(str)
		if err != nil {
			utils.Log.Err(err)
			return -1
		}

		err = utils.ForceCreateFilePath(str)
		if err != nil {
			utils.Log.Err(err)
			return -1
		}

		fd, err := os.OpenFile(str, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660)
		if err != nil {
			utils.Log.Err(err)
			return -1
		}

		this.lastfile = str
		this.file = fd
		if this.WBufSize > 0 {
			this.fileWriter = bufio.NewWriterSize(this.file, this.WBufSize)
		} else {
			this.fileWriter = bufio.NewWriter(this.file)
		}

		return 1
	} else {
		return 0
	}
}

func (this *CommRawFileWriter) tryWriteFile(buf []byte) bool {
	if this.file == nil {
		return false
	}
	_, err := this.fileWriter.Write(buf)
	if err != nil {
		utils.Log.Err(err)
		return false
	}
	return true
}
